package l1j.opqlo.AutoPay;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.TimerTask;
import java.util.concurrent.ScheduledFuture;
import java.util.logging.Level;
import java.util.logging.Logger;

import l1j.opqlo.NewSystem.A_ColorMessage;
import l1j.opqlo.NewSystem.各項記錄輸出;
import l1j.opqlo.Server.L1World.L1World;
import l1j.server.DatabaseFactory;
import l1j.server.Thread.GeneralThreadPool;
import l1j.server.Thread.PcOtherThreadPool;
import l1j.server.server.datatables.ItemTable;
import l1j.server.server.model.L1Object;
import l1j.server.server.model.Instance.L1ItemInstance;
import l1j.server.server.model.Instance.L1PcInstance;
import l1j.server.server.templates.L1Item;
import l1j.server.server.utils.SQLUtil;

public class AutoPayModel {
	class AutoPayTimer extends TimerTask {

		private ScheduledFuture<?> _timer;

		@Override
		public void run() {
			try {
				AutoPayModel.this.getPayTable();
				Thread.sleep(100);
				if (AutoPayModel.this._payList.isEmpty()) {
					return;
				}
				L1PcInstance pc = null;
				L1Object obj = null;
				MyPay_temp temp = null;
				ArrayList<L1ItemInstance> items;
				for (int i = 0; i < AutoPayModel.this._payList.size(); i++) {
					temp = AutoPayModel.this._payList.get(i);
					items = AutoPayModel.this.createItem(temp);
					obj = L1World.getInstance().findObject(temp.getObjId());
					if (obj != null) {
						if (obj instanceof L1PcInstance) {
							pc = (L1PcInstance) obj;
							if (pc.getAccountName().equalsIgnoreCase(temp.getAccountName())) {
								pc.getDwarfInventory().loadItems();
								if (items != null) {
									pc.sendPackets(new A_ColorMessage(1,"贊助款項 【" + temp.getAmount()+ "】 已查收完畢!"));
									for (final L1ItemInstance item : items) {
										pc.sendPackets(new A_ColorMessage(1,"你獲得" + item.getLogName() + "。"));
									}
									pc.sendPackets(new A_ColorMessage(1,"上列物品已發放至倉庫。"));
								}
							}
						}
						obj = null;
					}
					AutoPayModel.this.updateGive(temp.getTradeId());
					StringBuffer log = new StringBuffer();
					log.append("訂單編號: ").append(temp.getTradeId())
					.append("	帳號: ").append(temp.getAccountName())
					.append("	訂單金額: ").append(temp.getAmount())
					.append("	時間:")
					.append(new Timestamp(System.currentTimeMillis()))
					.append("\r\n");
					if(items !=null){
					for (final L1ItemInstance item : items) {
						log.append(item.getLogName()).append("	流水號: ")
						.append(item.getId()).append("	已發放至倉庫。")
						.append("\r\n");
					}
					}else{
						log.append("發送錯誤。 \r\n");
					}
					各項記錄輸出.LogSave(30, log.toString());
					log.delete(0, log.length());
					log = null;
					items.clear();
					items = null;
					Thread.sleep(10);
					temp.remove();
				}
			} catch (final Exception e) {
				_log.log(Level.WARNING, "時間軸異常重啟", e);
				GeneralThreadPool.getInstance().cancel(this._timer, false);
				final AutoPayTimer Timer = new AutoPayTimer();
				Timer.start();
			}
		}

		public void start() {
			final int timeMillis = 5000;// 1秒
			this._timer = PcOtherThreadPool.get().scheduleAtFixedRate(this,timeMillis, timeMillis);
		}
	}

	private static final Logger _log = Logger.getLogger(AutoPayModel.class
			.getName());
	private static AutoPayModel _instance;
	private static final HashMap<Integer, ArrayList<AutoPay_temp>> _list = new HashMap<Integer, ArrayList<AutoPay_temp>>();
	private static HashMap<Integer, Od_sob_temp> _odList;

	public static AutoPayModel getInstance() {
		if (_instance == null) {
			_instance = new AutoPayModel();
		}
		return _instance;
	}

	private final ArrayList<MyPay_temp> _payList = new ArrayList<MyPay_temp>();

	public AutoPayModel() {
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("SELECT * FROM zzz_mypay_list ");
			rs = pstm.executeQuery();
			while (rs.next()) {
				final AutoPay_temp temp = new AutoPay_temp();
				final int sob = rs.getInt("sob");
				ArrayList<AutoPay_temp> tempList;
				if (!_list.containsKey(sob)) {
					tempList = new ArrayList<AutoPay_temp>();
				} else {
					tempList = _list.get(sob);
					_list.remove(sob);
				}
				temp.setItemId(rs.getInt("itemId"));
				temp.setCount(rs.getInt("count"));
				temp.setPrice(rs.getInt("price"));
				temp.setBless(rs.getInt("bless"));
				temp.setEnchantLv(rs.getInt("EnchantLv"));
				temp.setDeadLine(rs.getTimestamp("deadline"));
				temp.setLv(rs.getInt("LV"));
				tempList.add(temp);
				_list.put(sob, tempList);
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(rs, pstm, con);
		}
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("SELECT * FROM zzz_od_sob ");
			rs = pstm.executeQuery();
			while (rs.next()) {
				final int oid = rs.getInt("O_id");
				if (oid > 1) {
					if (_odList == null) {
						_odList = new HashMap<Integer, Od_sob_temp>();
					}
					final Od_sob_temp temp = new Od_sob_temp();
					temp.setCash(rs.getInt("O_cash"));
					_odList.put(oid, temp);
				}
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(rs, pstm, con);
		}
	}

	private ArrayList<L1ItemInstance> createItem(final MyPay_temp mypay) {
		try {
			int sob = mypay.getSob();
			if (_odList.containsKey(sob)) {
				final int cash = _odList.get(sob).getCash() ;
				if(cash != mypay.getAmount() && mypay.getAmount() % cash !=0){
					return null;
				}
			}
			final ArrayList<AutoPay_temp> itemList = _list.get(sob);
			if (itemList == null) {
				return null;
			}

			final ArrayList<L1ItemInstance> itemsArray = new ArrayList<L1ItemInstance>();
			for (final AutoPay_temp Itemtemp : itemList) {
				final long deadline = Itemtemp.getDeadLine();
				if (deadline > 0 && mypay.getPayTime() > deadline) {
					continue;
				}
				final int count = Itemtemp.getTotalCount(mypay.getAmount());
				if (count < 1) {
					continue;
				}
				final L1Item temp = ItemTable.getInstance().getTemplate(Itemtemp.getItemId());
				if (temp !=null) {
					if(temp.isStackable()){
						final L1ItemInstance item = ItemTable.getInstance().createItem(Itemtemp.getItemId());
						item.setEnchantLevel(Itemtemp.getEnchantLv());
						item.setCount(count);
						item.setBless(Itemtemp.getBless());
						item.setLevel(Itemtemp.getLv());
						item.setIdentified(true);
						this.insertItem(item, mypay.getAccountName());
						itemsArray.add(item);
					}else{
						for(int i=0; i<count; i++){
							final L1ItemInstance item = ItemTable.getInstance().createItem(Itemtemp.getItemId());
							item.setEnchantLevel(Itemtemp.getEnchantLv());
							item.setCount(1);
							item.setBless(Itemtemp.getBless());
							item.setIdentified(true);
							item.setLevel(Itemtemp.getLv());
							this.insertItem(item, mypay.getAccountName());
							itemsArray.add(item);
						}
					}
				}
			}
			return itemsArray;
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		}
		return null;
	}

	private void getPayTable() {
		Connection con = null;
		PreparedStatement pstm = null;
		ResultSet rs = null;
		this._payList.clear();
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con
					.prepareStatement("SELECT * FROM zzz_mypay where give = 0");
			rs = pstm.executeQuery();
			while (rs.next()) {
				final MyPay_temp temp = new MyPay_temp();
				temp.setTradeId(rs.getInt("tradeid"));
				temp.setAccountName(rs.getString("account_name"));
				temp.setObjId(rs.getString("objid"));
				temp.setSob(rs.getString("Od_sob"));
				temp.setAmount(rs.getInt("Amount"));
				temp.setPayTime(rs.getString("Process_date"),
						rs.getString("Process_time"));
				this._payList.add(temp);
				Thread.sleep(10);
			}
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(rs, pstm, con);
		}
	}

	private void insertItem(final L1ItemInstance item, String accountname) {
		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con.prepareStatement("INSERT INTO character_warehouse SET id = ?, account_name = ?, item_id = ?, item_name = ?, count = ?, is_equipped=0, enchantlvl = ?, is_id = ?, durability = ?, charge_count = ?, remaining_time = ?, last_used = ?, bless = ?, attr_enchant_kind = ?, attr_enchant_level = ?, firemr = ?, watermr = ?, earthmr = ?, windmr = ?, addsp = ?, addhp = ?, addmp = ?, hpr = ?, mpr = ?, SkillType = ?, level=?, 屬性增傷=?, 六屬性加成=?, 破甲=?, 抵擋=?, 額外攻擊=?, 攻擊成功=?, 經驗=?, 爆擊=?, 大怪=?, 小怪=?, 魔防=?,種族增傷=? ,暈眩 =?, 石化 =?, 睡眠 =?, 凍結 =?, 支撐 =?, 暗黑 =?, 暈眩抗性=?, 石化抗性=? , 睡眠抗性=? , 凍結抗性=? , 支撐抗性=? , 暗黑抗性=? , 掉寶率=?");
			pstm.setInt(1, item.getId());
			pstm.setString(2, accountname);
			pstm.setInt(3, item.getItemId());
			pstm.setString(4, item.getName());
			pstm.setLong(5, item.getCount());
			pstm.setInt(6, item.getEnchantLevel());
			pstm.setInt(7, item.isIdentified() ? 1 : 0);
			pstm.setInt(8, item.get_durability());
			pstm.setInt(9, item.getChargeCount());
			pstm.setInt(10, item.getRemainingTime());
			pstm.setTimestamp(11, item.getLastUsed());
			pstm.setInt(12, item.getBless());
			pstm.setInt(13, item.getAttrEnchantKind());
			pstm.setInt(14, item.getAttrEnchantLevel());
			// TODO 飾品強化卷軸修正無法存取人物物品資料
			pstm.setInt(15, item.getFireMr());
			pstm.setInt(16, item.getWaterMr());
			pstm.setInt(17, item.getEarthMr());
			pstm.setInt(18, item.getWindMr());
			pstm.setInt(19, item.getaddSp());
			pstm.setInt(20, item.getaddHp());
			pstm.setInt(21, item.getaddMp());
			pstm.setInt(22, item.getHpr());
			pstm.setInt(23, item.getMpr());
			// TODO 飾品強化卷軸修正無法存取人物物品資料
			// TODO 魔法武器卷軸by missu0524
			pstm.setInt(24, item.getSkillType());
			// TODO 魔法武器卷軸by missu0524
			// opqlo 道具升級系統START
			pstm.setInt(25, item.getLevel());
			// opqlo 道具升級系統END
			pstm.setString(26, item.getLvStatus().saveItemSpecialDmg(0));
			pstm.setString(27, item.getLvStatus().saveItemSpecialDmg(1));
			pstm.setInt(28, item.getExtraDmg());
			pstm.setInt(29, item.getExtraDef());
			pstm.setInt(30, item.getModDmg());
			pstm.setInt(31, item.getModHit());
			pstm.setDouble(32, item.getExpUp());
			pstm.setDouble(33, item.getDoubleDmg());
			pstm.setDouble(34, item.getBigDmg());
			pstm.setDouble(35, item.getSmallDmg());
			pstm.setInt(36, item.getaddMr());
			pstm.setString(37, item.getLvStatus().saveItemSpecialDmg(2));
			pstm.setInt(38, item.getStunDice());
			pstm.setInt(39, item.getStoneDice());
			pstm.setInt(40, item.getSleepDice());
			pstm.setInt(41, item.getFreezeDice());
			pstm.setInt(42, item.getSustainDice());
			pstm.setInt(43, item.getBlindDice());
			pstm.setInt(44, item.getStunMr());
			pstm.setInt(45, item.getStoneMr());
			pstm.setInt(46, item.getSleepMr());
			pstm.setInt(47, item.getFreezeMr());
			pstm.setInt(48, item.getSustainMr());
			pstm.setInt(49, item.getBlindMr());
			pstm.setDouble(50, item.getDroprate());
			pstm.execute();
		} catch (final Exception e) {
			_log.log(Level.SEVERE, e.getLocalizedMessage(), e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}

	public void start() {
		new AutoPayTimer().start();
	}

	private void updateGive(final int tradeid) {

		Connection con = null;
		PreparedStatement pstm = null;
		try {
			con = DatabaseFactory.get().getConnection();
			pstm = con
					.prepareStatement("UPDATE zzz_mypay SET give = ? WHERE tradeid = ?");
			pstm.setString(1, "1");
			pstm.setInt(2, tradeid);
			pstm.execute();
		} catch (final Exception e) {
			_log.log(Level.SEVERE, "ブックマークの削除でエラーが発生しました。", e);
		} finally {
			SQLUtil.close(pstm);
			SQLUtil.close(con);
		}
	}

}
